package testing;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Random;

import com.thesis.algorithm.Device;
import com.thesis.algorithm.FileConverter;
import com.thesis.algorithm.Sequence;
import com.thesis.algorithm.SequenceElement;
import com.thesis.algorithm.SequenceMatching;
import com.thesis.utils.BusControl;
import com.thesis.utils.CONSTANTS;
import com.thesis.utils.Utils;
import com.thesis.utils.VelocityEstimate;
import com.thesis.utils.VelocityEstimateTest;
import com.thesis.utils.hVelocityEstimate;

public class hVelocityEstimateWrapper {
	int ESTI_LENGTH;
	LinkedList<Sequence> _TESTDATA = new LinkedList<Sequence>();
	SequenceMatching sm = new SequenceMatching(
			SequenceMatching.MODE_READ_FROM_BINARYFILE);
	BusControl busController = new BusControl();
	hVelocityEstimate ve;
	FileConverter fc = new FileConverter(CONSTANTS.TEST_DATA_FOLDER);

	public hVelocityEstimateWrapper() {
		// TODO Auto-generated constructor stub

		_TESTDATA = busController.produceTrainSequence(fc.listOfDevices);
		for (int i = 0; i < _TESTDATA.size(); i++) {
			System.out.println("TESTDATA" + _TESTDATA.get(i).BusRouteID + " "
					+ _TESTDATA.get(i).size());
		}
	}

	public void testBusStopAndPrintToFile(int sequence_length,
			Writer outSummary, int consider_length, Writer outExcel) {
		ESTI_LENGTH = consider_length;
		double SumDiffAll = 0;
		int allcount = 0;
		double allMax = 0;
		double allMin = 5000;
		double SumDiffSteps = 0;
		int stepcount = 0;
		double stepMax = 0;
		double stepMin = 5000;
		double GPSv = 0;
		double finalsteps = 0;
		double all = 0;

		try {
			
			//create files
			Writer out = new BufferedWriter(
					new OutputStreamWriter(new FileOutputStream(
							CONSTANTS.RESULT_FOLDER
									+ "velocityEstimate_sequenceLength"
									+ sequence_length + "T" + consider_length
									+ ".txt"), "UTF-8"));
			Writer out2 = new BufferedWriter(new OutputStreamWriter(
					new FileOutputStream(CONSTANTS.RESULT_FOLDER
							+ "velocityestimate_printout" + sequence_length
							+ "T" + consider_length + ".txt"), "UTF-8"));
			out2.write("GPSv\tall\tfinalsteps\tMath.abs(GPSv - all)\tMath.abs(GPSv - finalsteps)\n");
			
			
			//GPS INFO
			Random randomGenerator = new Random();
			LinkedList<VelocityEstimateTest> vet = new LinkedList<VelocityEstimateTest>();
			VelocityEstimateTest tmpvet;
			for (Device d : fc.listOfDevices) {
				tmpvet = new VelocityEstimateTest(d);
				vet.add(tmpvet);
			}

			
			//======TEST
			for (int i = 0; i < CONSTANTS.nExample; i++) {
				int fileindex = randomGenerator.nextInt(_TESTDATA.size()) - 1;
				if (fileindex == -1) {
					fileindex = 0;
				}

				int start = randomGenerator.nextInt(_TESTDATA.get(fileindex)
						.size() - sequence_length - 1);
				Sequence testdata = new Sequence();
				for (int j = start; j < start + sequence_length; j++) {
					testdata.add(new SequenceElement(_TESTDATA.get(fileindex).get(j)));
					testdata.getLast().Repetition = 1;
				}

				System.out.println("TEST " + (i + 1));
				out.write("TEST " + i + "\n");
				out.write("TEST REFINED1      :" + testdata.refineSequence().toString() + "\n");
				out.write("BUSROUTE           :" + _TESTDATA.get(fileindex).BusRouteID + "\n");

				// TEST, THEN hide the state here
				testdata.BusRouteID = _TESTDATA.get(fileindex).BusRouteID;
				all = testOnoriginalData(testdata.refineSequence(), out);
				
				
				// ==========GPS SPEED
				GPSv = vet.get(fileindex).returnVelocity(
						start + sequence_length - ESTI_LENGTH,
						start + sequence_length) * 3600;
				out.write("GPS velocity:" + GPSv + "km/h\n");

				
				
				//============TEST DIFFERENT LENGTH - BUSMATTCHING 
//				testVelocityEstimate(testdata, out, sm);
				// ===========VELOCITY ESTIMATE
				//finalsteps = testVelocityEstimate(testdata, out, sm);

			}
			// out2.write(GPSv + "\t" + all + "\t" + finalsteps + "\t "
			// + Math.abs(GPSv - all) + "\t"
			// + Math.abs(GPSv - finalsteps) + "\n");
			// if (all > 0.000001) {
			// SumDiffAll += Math.abs(GPSv - all);
			// allcount++;
			// if (Math.abs(GPSv - all) > allMax) {
			// allMax = Math.abs(GPSv - all);
			// }
			// if (Math.abs(GPSv - all) < allMin) {
			// allMin = Math.abs(GPSv - all);
			// }
			// }
			// if (finalsteps > 0.000001) {
			// SumDiffSteps += Math.abs(GPSv - finalsteps);
			// stepcount++;
			// if (Math.abs(GPSv - finalsteps) > stepMax) {
			// stepMax = Math.abs(GPSv - finalsteps);
			// }
			// if (Math.abs(GPSv - finalsteps) < stepMin) {
			// stepMin = Math.abs(GPSv - finalsteps);
			// }
			// }
			// }
			// out.write("ALL MIN      :" + allMin + "\n");
			// out.write("ALL MAX      :" + allMax + "\n");
			// out.write("ALL AVG      :" + (SumDiffAll / allcount) + "\n");
			// out.write("STEP MIN      :" + stepMin + "\n");
			// out.write("STEP MAX      :" + stepMax + "\n");
			// out.write("STEP AVG      :" + (SumDiffSteps / stepcount) + "\n");
			// out2.write("ALL MIN      :" + allMin + "\n");
			// out2.write("ALL MAX      :" + allMax + "\n");
			// out2.write("ALL AVG      :" + (SumDiffAll / allcount) + "\n");
			// out2.write("STEP MIN      :" + stepMin + "\n");
			// out2.write("STEP MAX      :" + stepMax + "\n");
			// out2.write("STEP AVG      :" + (SumDiffSteps / stepcount) +
			// "\n");
			out.write("\n\n\n\n");			
			out.close();
			// out2.close();

		} catch (Exception e) {
			System.err.println(e.getMessage());
			e.printStackTrace();
		}

	}

	private double testOnoriginalData(Sequence data, Writer out) throws IOException {
		ve = new hVelocityEstimate(busController);
		double result = 0;
		int timeStamp = 0;
		//short[] interestedBusRoute = sm.possibleBusRoute(data);
		short[] interestedBusRoute = {(short) data.BusRouteID};
		LinkedList<Character> interestedBustopID = new LinkedList<Character>();
		out.write("BUSROUTE: " + data.BusRouteID+"\n");
		for (int i = 0; i < data.size(); i++) {
			interestedBustopID = new LinkedList<Character>();
			interestedBustopID.add(data.get(i).State);
			//interestedBusRoute = sm.possibleBusRoute(data.get(i).Observation);
			//out.write(Utils.arrayToString(interestedBusRoute)+"\n");
			ve.Add(timeStamp, interestedBustopID, interestedBusRoute);
			timeStamp += data.get(i).Repetition;
		}
		out.write("\n");
		ve.Add(timeStamp, interestedBustopID, interestedBusRoute);

		result = ve.returnVelocity(data.score() - ESTI_LENGTH, data.score(), out);
		out.write("CELL ID VELOCITY: " + result * 3600 + "km/h\n");
		return (result * 3600);
	}

	private double testVelocityEstimate(Sequence sequence, Writer out,	SequenceMatching sm) throws IOException {

		ve = new hVelocityEstimate(busController);
		Sequence testsequence = new Sequence();
		double result = 0;
		int interval = 30;

		for (int i = 0; i < sequence.size(); ++i) {
			//test only with an interval
			testsequence.sequenceinFile.addLast(sequence.get(i));
			if ((i % interval) != (interval - 1))
				continue;
			
			//test
			out.write("TEST with: " + testsequence.size());
			LinkedList<Character> busStops = new LinkedList<Character>();
			busStops = sm.matchBusStop(testsequence, out,CONSTANTS.ALLBUSROUTE);
			if (busStops == null || busStops.size() == 0)
				continue;
			
			short[] interestedBusRoute = sm.possibleBusRoute(testsequence);
			ve.Add(i, busStops, interestedBusRoute);
			out.write("added route: " + Utils.arrayToString(interestedBusRoute));
			out.write("\nadded bstop: " + Utils.linkedListToString(busStops));
			out.write("\nat: " + i);
			out.write("\nresult from 0 " + " to " + testsequence.score());
			result = ve.returnVelocity(0, testsequence.score(), out);
			out.write("\nVELOCITY: " + result * 3600 + "km/h\n");
		}
		out.write("END TEST\n\n\n\n\n");
		return (ve.returnVelocity(testsequence.score() - ESTI_LENGTH,
				testsequence.score(),out) * 3600);
	}
}
